﻿using System;
using System.Collections.Generic;
#if DEBUG
using System.Diagnostics;
#endif // #if DEBUG
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using FRL.DebtChased.Silverlight.Library;
using FRL.DebtChased.Silverlight.Library.RichContentService;
using FRL.DebtChased.WorkflowObjects;

namespace FRL.DebtChased.WorkflowEditor
{

	/// <summary>
	/// Declaration of WorkflowEditingCtrl class
	/// The main workflow editing control
	/// </summary>
	public partial class WorkflowEditingCtrl : UserControl
	{

		/////////////////////////////////////////////////////////////
		// Attributes

		private string m_strWorkflowNotes;

		private int m_iWorkflowId;

		private int m_iAccountInvoiceStatusId;

		private bool m_bIsInstalmentStatus;

		private int m_iPayDay;

		/////////////////////////////////////////////////////////////
		// Construction

		public WorkflowEditingCtrl()
		{

			// Load xaml resources
			InitializeComponent();

			// Hide the add-panel
#if DEBUG
			addActionHeadingBarCtrl.IsArrowUp = false;
#else
			addActionHeadingBarCtrl.IsArrowUp = true;
			pnlAddAction.Height = 0;
			pnlAddAction.Visibility = System.Windows.Visibility.Collapsed;
			AddActionPanelAnimation_Completed(null, null);
#endif // #if !DEBUG

		}

		/////////////////////////////////////////////////////////////
		// Event Handlers

		private void butDeleteActions_Click(object sender, RoutedEventArgs e)
		{

			// Pass request to the planner
			plannerCanvas.DeleteSelected();

		}

		private void butEditAction_Click(object sender, RoutedEventArgs e)
		{

			// Pass request to the planner
			plannerCanvas.EditSelected();

		}

		private void butIncDays_Click(object sender, RoutedEventArgs e)
		{

			// Pass to the panner window
			plannerCanvas.IncDays(true, 1);

		}

		private void butDecDays_Click(object sender, RoutedEventArgs e)
		{

			// Pass to the panner window
			plannerCanvas.IncDays(false, 1);

		}

		private void butIncPayDay_Click(object sender, RoutedEventArgs e)
		{

			// Calc the new pay-day
			m_iPayDay++;
			_updatePayDay(true);

		}

		private void butDecPayDay_Click(object sender, RoutedEventArgs e)
		{

			// Calc the new pay-day
			m_iPayDay--;
			_updatePayDay(true);

		}

		private void butRevert_Click(object sender, RoutedEventArgs e)
		{

			try
			{

				// Start by downloading the supporting data
				RichContentServiceClient proxy = new RichContentServiceClient();
				proxy.GetWorkflowXmlCompleted += new EventHandler<GetWorkflowXmlCompletedEventArgs>(proxy_GetWorkflowXmlCompleted);
				proxy.Endpoint.Address = ExtensionsForSilverlight.CreateDebtChasedEndpoint();
				proxy.GetWorkflowXmlAsync(m_iWorkflowId);

				// Show hourglass
				MainPage.Singleton.hourglassCtrl.IncShowCount(true);

			}
			catch (Exception x)
			{

				// Message for user
				MessageBoxes.PopupMessage_InternalError(string.Format("Failed to revert workflow.\n\n{0}", x.Message));

			}

		}

		void proxy_GetWorkflowXmlCompleted(object sender, GetWorkflowXmlCompletedEventArgs e)
		{

			// Hide hourglass
			MainPage.Singleton.hourglassCtrl.IncShowCount(false);

			// If the call failed...
			if (e.Error != null)
			{
				MessageBoxes.PopupMessage(e.Error.Message);
			}
			else if (e.Result == null)
			{
#if DEBUG
				Debug.Assert(false);
#endif // #if DEBUG
				MessageBoxes.PopupMessage_InternalError("Failed to load workflow from server.");
			}
			else
			{

				// Unwrap the workflow
				FRL.DebtChased.WorkflowObjects.Workflow wf = FRL.DebtChased.WorkflowObjects.Workflow.XmlFactory(e.Result.Buffer);
				if (wf != null)
				{

					// Show the workflow ctrl
					this.SetWorkflow(
						e.Result.WorkflowId, 
						e.Result.AccountInvoiceStatusId,
						e.Result.IsInstalmentPlanStatus,
						wf
					);

				}
				else
					MessageBoxes.PopupMessage_InternalError("Cannot load workflow.  Failed to unwrap xml data.");

			}

		}

		private void butSave_Click(object sender, RoutedEventArgs e)
		{

			// Get the workflow and convert to a buffer
			FRL.DebtChased.WorkflowObjects.Workflow workflow = _getWorkflow();
			byte[] buffer = workflow.ToXmlBuffer();

			try
			{

				// Send to the web service
				RichContentServiceClient proxy = new RichContentServiceClient();
				proxy.Endpoint.Address = ExtensionsForSilverlight.CreateDebtChasedEndpoint();
				proxy.SetWorkflowXmlCompleted += new EventHandler<SetWorkflowXmlCompletedEventArgs>(proxy_SetWorkflowXmlCompleted);
				proxy.SetWorkflowXmlAsync( m_iWorkflowId, buffer, m_iAccountInvoiceStatusId );

				// Show hourglass
				MainPage.Singleton.hourglassCtrl.IncShowCount(true);

			}
			catch (Exception x)
			{

				// Message for user
				MessageBoxes.PopupMessage_InternalError(string.Format("Failed to save workflow.\n\n{0}", x.Message));

			}

		}

		void proxy_SetWorkflowXmlCompleted(object sender, SetWorkflowXmlCompletedEventArgs e)
		{

			// Hide hourglass
			MainPage.Singleton.hourglassCtrl.IncShowCount(false);

			// Get the result
			if (e.Error != null)
				MessageBoxes.PopupMessage(e.Error.Message);
			else if (e.Result != null)
				MessageBoxes.PopupMessage(e.Result);
			else
				m_iWorkflowId = e.iWorkflowId;

			// Setup controls
			_setupControls();

		}

		private void butClose_Click(object sender, RoutedEventArgs e)
		{

			// Inform the main window
			MainPage.Singleton.CloseWorkflowEditingCtrl();

		}

		private void UserControl_KeyDown(object sender, KeyEventArgs e)
		{

			// If this is the delete key...
			if (e.Key == Key.Delete)
			{

				// Pass request to the planner
				plannerCanvas.DeleteSelected();

			}
			else if (e.Key == Key.Escape)
			{

				// Pass request to the planner
				plannerCanvas.ClearSelection();

			}

		}

		private void hypWorkflowName_Click(object sender, RoutedEventArgs e)
		{

			// Show properties
			WorkflowPropertiesWnd wnd = new WorkflowPropertiesWnd(
				hypWorkflowName.Content.ToString(),
				m_strWorkflowNotes
			);
			wnd.Closed += new EventHandler(WorkflowPropertiesWnd_Closed);
			wnd.Show();

		}

		void WorkflowPropertiesWnd_Closed(object sender, EventArgs e)
		{

			// Called after workflow properties have been edited
			WorkflowPropertiesWnd wnd = sender as WorkflowPropertiesWnd;

			// Update hyperlink
			hypWorkflowName.Content = wnd.txtName.Text;

			// Update notes
			m_strWorkflowNotes = wnd.txtNotes.Text;

		}

		private void AddActionHeadingBarCtrl_ExpandChange(object sender, EventArgs e)
		{

			// Get the height of the add-panel
			double dblPanelHeight = pnlAddAction.Height;
			if (double.IsNaN(dblPanelHeight))
				dblPanelHeight = pnlAddAction.ActualHeight;

			// Create easing function
			EasingFunctionBase func = new CircleEase();
			func.EasingMode = EasingMode.EaseInOut;

			// Create animations for the planner and the add-action panels
			DoubleAnimation animPanel = new DoubleAnimation();
			animPanel.Duration = new Duration(new TimeSpan(50 * 1000 * 100));
			animPanel.EasingFunction = func;

			// Add events
			animPanel.Completed += new EventHandler(AddActionPanelAnimation_Completed);
			animPanel.From = dblPanelHeight;

			// If hiding...
			if (dblPanelHeight > 0)
			{
				animPanel.To = 0;
				addActionHeadingBarCtrl.IsArrowUp = true;
			}
			else
			{
				pnlAddAction.Visibility = System.Windows.Visibility.Visible;
				animPanel.To = pnlAddAction.MaxHeight;
				addActionHeadingBarCtrl.IsArrowUp = false;
			}

			// Setup the story board
			Storyboard storyboard = new Storyboard();
			storyboard.Children.Add(animPanel);
			Storyboard.SetTarget(animPanel, pnlAddAction);
			Storyboard.SetTargetProperty(animPanel, new PropertyPath("(Height)"));

			// Begin the storyboard
			storyboard.Begin();

		}

		void AddActionPanelAnimation_Completed(object sender, EventArgs e)
		{

			// If the panel is minimized...
			if (pnlAddAction.Height == 0)
			{

				// Hide the panel
				pnlAddAction.Visibility = System.Windows.Visibility.Collapsed;

			}
			else
			{

			}

		}

		/////////////////////////////////////////////////////////////
		// Operations

		public void SetWorkflow(int iWorkflowId, int iAccountInvoiceStatusId, bool bIsInstalmentStatus, FRL.DebtChased.WorkflowObjects.Workflow wf)
		{

			// Retain the id
			m_iWorkflowId = iWorkflowId;
			m_bIsInstalmentStatus = bIsInstalmentStatus;
			m_iAccountInvoiceStatusId = iAccountInvoiceStatusId;

			// If this workflow doesn't have a name...
			if (string.IsNullOrEmpty(wf.Name))
				wf.Name = "New Workflow";

			// Set name label
			hypWorkflowName.Content = wf.Name;

			// Retain the notes
			m_strWorkflowNotes = wf.Notes;

			// Set the planner
			plannerCanvas.SetWorkflow(wf,bIsInstalmentStatus);

			// Update pay-day
			m_iPayDay = wf.PayDay;
			_updatePayDay(false);

			// Setup controls
			_setupControls();

		}

		private void _updatePayDay(bool bAnimate)
		{

			// If this is an instalment-status...
			if (m_bIsInstalmentStatus)
			{

				// Update text
				lbPayDay.Text = m_iPayDay.ToString();

				// Update controls
				butIncPayDay.IsEnabled = (m_iPayDay < plannerCanvas.GetTotalDays());
				butDecPayDay.IsEnabled = (m_iPayDay > 1);

				// Move the marker
				plannerCanvas.MovePayDayMarker(m_iPayDay, bAnimate);

			}

		}

		private FRL.DebtChased.WorkflowObjects.Workflow _getWorkflow()
		{

			// Declare return variable
			FRL.DebtChased.WorkflowObjects.Workflow Ftmp = new FRL.DebtChased.WorkflowObjects.Workflow();
			Ftmp.Name = hypWorkflowName.Content.ToString();
			Ftmp.Notes = m_strWorkflowNotes;
			Ftmp.PayDay = m_iPayDay;

			// Load the items from the planner
			plannerCanvas.GetWorkflow(Ftmp);

			// Return variable
			return Ftmp;

		}

		public void SupportDataLoaded()
		{

			// Inform panels
			pnlAddAction.SupportDataLoaded();

		}

		public void SelectionChanged(bool bIsActionSelected)
		{

			// Update controls
			_setupControls();

		}

		public void UpdateDaysAndPayDayAfterChange(int iDays, bool bCanDeleteBottomDay)
		{

			// Setup controls - Days
			lbTotalDays.Text = iDays.ToString();
			butIncDays.IsEnabled = (iDays < 98);
			butDecDays.IsEnabled = bCanDeleteBottomDay;

			// Setup controls - Pay Day
			if (m_bIsInstalmentStatus)
			{
				if (m_iPayDay > iDays)
					m_iPayDay = iDays;
				_updatePayDay(false);
			}

			// Setup controls
			_setupControls();

		}

		private void _setupControls()
		{

			// Enable/disable controls
			butEdit.IsEnabled = plannerCanvas.IsActionSelected;
			butDeleteActions.IsEnabled = plannerCanvas.IsActionSelected;
			butRevert.IsEnabled = (m_iWorkflowId != 0);

			// Show/hide controls
			gridPayDay.Visibility = m_bIsInstalmentStatus ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
			stackPayDay.Visibility = gridPayDay.Visibility;			

		}

	}

}
